﻿#region Copyright ©2008-2011, Technische Universitaet Muenchen

// ====================================================================================================
//
// Last Changed by       $Author: then $
// Last Changed Date     $LastChangedDate: 2009-03-19 13:58:26 +0100 (Thu, 19 Mar 2009) $
// Last Changed Revision $Rev: 42 $
//
// ====================================================================================================

#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
using Tum.CollabXT.DocxGen.Resources;
using Tum.CollabXT.DocxGen.Properties;
using TUM.Mustertexte_Parser;
using System.Windows.Controls;

#endregion

namespace Tum.CollabXT.DocxGen
{
    /// <summary>
    /// Interaction logic for DocxConfigPage.xaml
    /// </summary>
    public partial class DocxConfigPage : ToolProviderConfigPage
    {
        private DocxGen ToolProvider;
        private IConversionWorkflow ConversionWorkflow;

        /// <summary>
        /// Setting this to true disables event processing for the template tree control.
        /// This allows selective checking of the previously chosen elements without interference of the event handling.
        /// </summary>
        private bool Initializing;


        public DocxConfigPage()
        {
            InitializeComponent();
        }

        public override void ReceiveProviderHandle(IToolProvider toolProvider)
        {
            if (toolProvider == null) throw new ArgumentNullException("toolProvider");

            ToolProvider = (DocxGen) toolProvider;
            if (Directory.Exists(Settings.Default.LastTemplatePath))
                ToolProvider.TemplatePath = Settings.Default.LastTemplatePath;

            SetValues();
            SetProductsList();
        }

        public override void ReceiveWorkflowHandle(IConversionWorkflow workflow)
        {
            ConversionWorkflow = workflow;

            UpdateWorkflowButtons();
        }

        private void UpdateWorkflowButtons()
        {
            if (ToolProvider != null)
            {
                ConversionWorkflow.UpdateButtonState(true, ToolProvider.OutputPath != null && ToolProvider.TemplatePath != null);
            }
        }

        public override bool PrevPageRequested()
        {
            GetValues();
            return base.PrevPageRequested();
        }

        public override bool NextPageRequested()
        {
            GetValues();
            return base.NextPageRequested();
        }

        private void GetValues()
        {
            ToolProvider.ProductsToGenerated.Clear();
            foreach (CheckableTreeItem curDisciplineItem in treeViewProducts.Items)
            {
                if (curDisciplineItem.IsChecked != null && !curDisciplineItem.IsChecked.Value)
                    continue;

                foreach (CheckableTreeItem curProductItem in curDisciplineItem.Children)
                {
                    if (curProductItem.IsChecked == null || curProductItem.IsChecked.Value)
                    {
                        Tree<TemplateSerializationItem> templateTextsTree = new Tree<TemplateSerializationItem>();
                        GetValues_CreateSelectedTemplateTextsTree(curProductItem, templateTextsTree);

                        ToolProvider.ProductsToGenerated.Add(((ArtifactItemTag)curProductItem.Tag).Artifact.Id.ToLower(), templateTextsTree);
                    }
                }
            }
        }

        private static void GetValues_CreateSelectedTemplateTextsTree(CheckableTreeItem curTreeItemControl, TreeItem<TemplateSerializationItem> curParentItem)
        {
            foreach (CheckableTreeItem curChildItem in curTreeItemControl.Children)
            {
                if (curChildItem.IsChecked == null || curChildItem.IsChecked.Value)
                {
                    TemplateSerializationItem newTemplateTreeItemVal = null;
                    if (curChildItem.Tag is TopicEntry)
                        newTemplateTreeItemVal = new TemplateSerializationTopic() { Name = ((TopicEntry)curChildItem.Tag).Topic.Name };
                    else if (curChildItem.Tag is TextTemplate)
                        newTemplateTreeItemVal = new TemplateSerializationText() { Name = ((TextTemplate)curChildItem.Tag).Name };
                    else
                        continue;

                    var newTemplateTreeItem = curParentItem.AppendChild(newTemplateTreeItemVal);
                    GetValues_CreateSelectedTemplateTextsTree(curChildItem, newTemplateTreeItem);
                }
            }
        }

        private void SetValues()
        {
            //Output path
            if (ToolProvider.OutputPath == null)
                labelOutputPathValue.Content = CollabXT.DocxGen.Resources.Language.PathNotSet;
            else
            {
                labelOutputPathValue.Content = ToolProvider.OutputPath;
                labelOutputPathValue.Foreground = new SolidColorBrush(Color.FromRgb(0, 0, 0));
            }

            //Project name
            if (ToolProvider.ProjectName != null)
                textBoxProjectName.Text = ToolProvider.ProjectName;

            //Company
            if (ToolProvider.Company != null)
                textBoxCompanyName.Text = ToolProvider.Company;
            
            //Author
            if (ToolProvider.Author != null)
                textBoxAuthorName.Text = ToolProvider.Author;

            //Mustertexte
           if(string.IsNullOrEmpty(ToolProvider.TemplateTextsPath))
              labelTemplateTextsPathValue.Content = CollabXT.DocxGen.Resources.Language.PathNotSet;
           else
           {
              labelTemplateTextsPathValue.Content = ToolProvider.TemplateTextsPath;
              labelTemplateTextsPathValue.Foreground = new SolidColorBrush(Color.FromRgb(0, 0, 0));
           }

            //Template path
            if (ToolProvider.TemplatePath == null)
                labelTemplatePathValue.Content = CollabXT.DocxGen.Resources.Language.PathNotSet;
            else
            {
                labelTemplatePathValue.Content = ToolProvider.TemplatePath;
                labelTemplatePathValue.Foreground = new SolidColorBrush(Color.FromRgb(0, 0, 0));
            }

            //Button states
            UpdateWorkflowButtons();
        }

        private void SetProductsList()
        {
            //Product list
            treeViewProducts.Items.Clear();

            treeViewProducts.BeginInit();

            CheckableTreeItem artifactsWithoutDisciplineNode = null;

            //Insert disciplines
            var disciplinePositionDictionary = new Dictionary<string, int>();
            foreach (IDiscipline curDiscipline in ToolProvider.ProcessProvider.Disciplines)
            {
                var tvi = new CheckableTreeItem(curDiscipline.Name) { Tag = curDiscipline };
                disciplinePositionDictionary.Add(curDiscipline.Id, treeViewProducts.Items.Add(tvi));
            }

            //Insert products
            foreach (IArtifact curProd in ToolProvider.ProcessProvider.Artifacts)
            {
                CheckableTreeItem discTvi;

                var discAssoc = ToolProvider.ProcessProvider.GetAssociationsWithSource<IArtifact, IDiscipline>(curProd);
                if (discAssoc.Length == 0)
                {
                    //Check if node for artifacts without discipline has already been created
                    if (artifactsWithoutDisciplineNode == null)
                    {
                        artifactsWithoutDisciplineNode = new CheckableTreeItem("No discipline"); ///TODO: Localize
                        treeViewProducts.Items.Add(artifactsWithoutDisciplineNode);
                    }
                    discTvi = artifactsWithoutDisciplineNode;
                }
                else
                {
                    discTvi = treeViewProducts.Items.GetItemAt(disciplinePositionDictionary[discAssoc[0].DestinationId]) as CheckableTreeItem;

                    ///TODO: Case of multiple disciplines is ignored at the moment - change?
                }

                //Create artifact tree item and add Mustertext nodes if possible
                var newCti = new CheckableTreeItem(curProd.Name);
                newCti.PropertyChanged += new PropertyChangedEventHandler(TreeItemCheckBox_PropertyChanged);
                newCti.AutoSubCheck = false;

                var itemTag = new ArtifactItemTag { Artifact = curProd };

                if (!string.IsNullOrEmpty((string)labelTemplateTextsPathValue.Content) && (string)labelTemplateTextsPathValue.Content != CollabXT.DocxGen.Resources.Language.PathNotSet)
                    itemTag.TextTemplateParser = TemplateParser.CreateTemplateParser((string)labelTemplateTextsPathValue.Content, curProd.Name);

                var topics = DocumentGenerator.GetTopics(curProd, null, ToolProvider.ProcessProvider);
                if (topics != null)
                {
                    for (int a = 0; a < topics.Length; a++)
                    {
                        //Write missing topic
                        if (itemTag.TextTemplateParser != null)
                            topics[a].Template = itemTag.TextTemplateParser.GetTopicByName(topics[a].Topic.Name);

                        //Create tree item
                        var topicItem = new CheckableTreeItem(Tum.CollabXT.DocxGen.Resources.Language.ConfigPage_TreeAdditionalTopic + " " + topics[a].Topic.Name);
                        topicItem.PropertyChanged += new PropertyChangedEventHandler(TreeItemCheckBox_PropertyChanged);
                        topicItem.AutoSubCheck = false;
                        topicItem.Tag = topics[a];
                        newCti.Children.Add(topicItem);

                        //Write subitems
                        PopulateTextTemplateItem(topicItem, topics[a].Topic, topics[a].Template);
                    }
                }

                newCti.Tag = itemTag;
                newCti.PropertyChanged += TreeItemCheckBox_PropertyChanged;
                discTvi.Children.Add(newCti);
            }
            //------------

            foreach (CheckableTreeItem TreeRootElement in treeViewProducts.Items)
            {
                TreeRootElement.Initialize();

                foreach (CheckableTreeItem childCti in TreeRootElement.Children)
                {
                    var artifactId = (childCti.Tag as ArtifactItemTag).Artifact.Id.ToLower();

                    if (childCti.Tag != null && childCti.Tag is ArtifactItemTag)
                        childCti.IsChecked = ToolProvider.ProductsToGenerated.ContainsKey(artifactId);
                    else
                        childCti.IsChecked = false;
                    if (childCti.IsChecked == null || childCti.IsChecked.Value)
                    {
                        SetValues_CheckSelectedTemplateTexts(childCti, ToolProvider.ProductsToGenerated[artifactId]);
                    }
                }
            }

            treeViewProducts.EndInit();
        }

        private static void SetValues_CheckSelectedTemplateTexts(CheckableTreeItem curTreeItemControl, TreeItem<TemplateSerializationItem> curParentItem)
        {
            if (curParentItem == null/* || curParentItem.Children.Length == 0*/)
                return;

            foreach (var curTreeChild in curTreeItemControl.Children)
            {
                string itemName;
                if (curTreeChild.Tag is TopicEntry)
                    itemName = ((TopicEntry)curTreeChild.Tag).Topic.Name;
                else if (curTreeChild.Tag is TextTemplate)
                    itemName = ((TextTemplate)curTreeChild.Tag).Name;
                else
                    continue;

                curTreeChild.IsChecked = false;
                foreach (var curDataTreeItem in curParentItem.Children)
                {
                    if (((curTreeChild.Tag is TopicEntry && curDataTreeItem.Value is TemplateSerializationTopic) ||
                        (curTreeChild.Tag is TextTemplate && curDataTreeItem.Value is TemplateSerializationText)) && curDataTreeItem.Value.Name.Equals(itemName))
                    {
                        curTreeChild.IsChecked = true;
                        SetValues_CheckSelectedTemplateTexts(curTreeChild, curDataTreeItem);
                    }
                }
            }
        }

        private void PopulateTextTemplateItem(CheckableTreeItem item, ITopic topic, TemplateTopic templateTopic)
        {
            if (templateTopic != null)
            {
                foreach (var curTemplate in templateTopic.Templates)
                {
                    var templateItem = new CheckableTreeItem(Tum.CollabXT.DocxGen.Resources.Language.ConfigPage_TreeTextTemplate + " " + curTemplate.Name);
                    templateItem.Tag = curTemplate;
                    templateItem.AutoSubCheck = false;
                    item.Children.Add(templateItem);
                }
            }
            foreach (var curSubtopic in DocumentGenerator.GetTopics(topic, templateTopic, ToolProvider.ProcessProvider))
            {
                var topicItem = new CheckableTreeItem(Tum.CollabXT.DocxGen.Resources.Language.ConfigPage_TreeAdditionalTopic + " " + curSubtopic.Topic.Name);
                topicItem.PropertyChanged += new PropertyChangedEventHandler(TreeItemCheckBox_PropertyChanged);
                topicItem.Tag = curSubtopic;
                topicItem.AutoSubCheck = false;
                item.Children.Add(topicItem);
                PopulateTextTemplateItem(topicItem, curSubtopic.Topic, curSubtopic.Template);
            }
        }

        /// <summary>
        /// Checked state has changed. Modify products to be generated accordingly.
        /// </summary>
        /// <param name="sender">Item of which the check state has changed.</param>
        /// <param name="e">Information about the changed parameter.</param>
        private void TreeItemCheckBox_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (Initializing)
                return;

            ConversionWorkflow.InvalidateProcessing();

            var senderItem = sender as CheckableTreeItem;
            if (senderItem.IsChecked == null || senderItem.IsChecked == true)
            {
                //Set sub-items to default selection
                Initializing = true;
                CheckDefaultItems(senderItem);
                Initializing = false;
            }
        }

        private static bool? CheckDefaultItems(CheckableTreeItem treeItem)
        {
            bool def = true;
            if (treeItem.Tag is TextTemplate)
                def = ((TextTemplate)treeItem.Tag).Default;
            else if (treeItem.Tag is TopicEntry)
            {
                TopicEntry te = (TopicEntry)treeItem.Tag;
                if (te.Template is AdditionalProductTopic)
                    def = ((AdditionalProductTopic)te.Template).Default;
                else
                    def = true;
            }
            if (!def)
                return false;

            //Check sub items
            bool? foundCheckedItem = true;
            foreach (var curChild in treeItem.Children)
            {
                bool? checkResult = CheckDefaultItems(curChild);
                if (foundCheckedItem != null && foundCheckedItem.Value && (checkResult == null || !checkResult.Value))
                    foundCheckedItem = null;
            }

            treeItem.IsChecked = foundCheckedItem;
            return foundCheckedItem;
        }

        private void buttonSetTemplatePath_Click(object sender, RoutedEventArgs e)
        {
            var fbd = new FolderBrowserDialog {ShowNewFolderButton = false};

            if (Directory.Exists(Settings.Default.LastTemplatePath))
                fbd.SelectedPath = Settings.Default.LastTemplatePath;

            if (fbd.ShowDialog() == DialogResult.OK)
            {
                ToolProvider.TemplatePath = fbd.SelectedPath;
                ConversionWorkflow.InvalidateProcessing();
                SetValues();

                //Save path as 'last template path'
                Settings.Default.LastTemplatePath = ToolProvider.TemplatePath;
                Settings.Default.Save();
            }
        }

        private void buttonSetOutputPath_Click(object sender, RoutedEventArgs e)
        {
            var fbd = new FolderBrowserDialog {ShowNewFolderButton = true};

            if (Directory.Exists(Settings.Default.LastOutputPath))
                fbd.SelectedPath = Settings.Default.LastOutputPath;

            if (fbd.ShowDialog() == DialogResult.OK)
            {
                ToolProvider.OutputPath = fbd.SelectedPath;
                ConversionWorkflow.InvalidateProcessing();
                SetValues();

                Settings.Default.LastOutputPath = fbd.SelectedPath;
                Settings.Default.Save();
            }
        }

        private void buttonSetTemplateTextsPath_Click(object sender, RoutedEventArgs e)
        {
            var openFileDlg = new OpenFileDialog
                                  {
                                      Filter = Tum.CollabXT.DocxGen.Resources.Language.ConfigPage_OpenTextTemplatesFilter + "|*.xml",
                                      Multiselect = false,
                                      RestoreDirectory = true
                                  };

            if (openFileDlg.ShowDialog() == DialogResult.OK)
            {
                ToolProvider.TemplateTextsPath = openFileDlg.FileName;
                ConversionWorkflow.InvalidateProcessing();
                SetValues();
                SetProductsList();

                Settings.Default.LastTemplateTextPath = openFileDlg.FileName;
                Settings.Default.Save();
            }
        }


        private class ArtifactItemTag
        {
            public IArtifact Artifact;
            public TemplateParser TextTemplateParser;
        }

        private void textBoxProjectName_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (ToolProvider != null)
                ToolProvider.ProjectName = textBoxProjectName.Text;
        }

        private void textBoxCompanyName_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (ToolProvider != null)
                ToolProvider.Company = textBoxCompanyName.Text;
        }

        private void textBoxAuthorName_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (ToolProvider != null)
                ToolProvider.Author = textBoxAuthorName.Text;
        }
    }
}